package net.peelmeagrape.hibernate;

import net.peelmeagrape.hibernate.xmlgen.XmlAttribute;
import net.peelmeagrape.hibernate.xmlgen.XmlElement;

import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * allows the definition of a named, logical grouping of properties of a class.
 * The most important use of the construct is that it allows a combination of properties
 * to be the target of a property-ref (
 * {@link net.peelmeagrape.hibernate.ManyToOne#propertyRef()},
 * {@link net.peelmeagrape.hibernate.OneToOne#propertyRef()},
 * {@link net.peelmeagrape.hibernate.collections.Key#propertyRef()}).
 * It is also a convenient way to define a multi-column unique constraint. Specify
 * using the {@link net.peelmeagrape.hibernate.H8Class#properties()} setting.
 * <br/>
 * <br/>
 * A property, or many-to-one property is included in a {@link Properties}
 * element using the {@link net.peelmeagrape.hibernate.Property#properties()},
 * {@link net.peelmeagrape.hibernate.ManyToOne#properties()}, or
 * {@link net.peelmeagrape.hibernate.Component#properties()} settings, the
 * value of which must match the {@link #name()} value.
 * <br/>
 * <br/>
 * For example, if we have the following Properties mapping:
 * <pre>
    &#64;{@link H8Class}( properties = &#64;{@link Properties}(name="name"))
    class Person {
        &#64;{@link Property}(properties="name") String firstName;
        &#64;{@link Property}(properties="name") String lastName;
    }
 </pre>
 * Then we might have some legacy data association which refers to this unique key
 * of the Person table, instead of to the primary key:
 * <pre>
    &#64;{@link ManyToOne}( propertyRef = "name",
        columnMapping = {
            &#64;{@link Column}(name="firstName"),
            &#64;{@link Column}(name="lastName")
        }
    )
    private Person person;
 </pre>
 * We don't recommend the use of this kind of thing outside the context of mapping legacy data.
 */
@Retention(RUNTIME)
@XmlElement(name="properties")
public @interface Properties
{
    /**
     * The logical name of the grouping - not an actual property name.
     */
    @XmlAttribute String name();

    /**
     * Specifies that a unique constraint exists upon all mapped columns of the component.
     */
    @XmlAttribute boolean unique() default false;

    /**
     * Do the mapped columns appear in SQL INSERTs?
     */
    @XmlAttribute boolean insert() default true;

    /**
     * Do the mapped columns appear in SQL UPDATEs?
     */
    @XmlAttribute boolean update() default true;

    /**
     * Specifies that updates to these properties do or do not require acquisition of the optimistic lock.
     * In other words, determines if a version increment should occur when these properties are dirty.
     */
    @XmlAttribute("optimistic-lock") boolean optimisticLock() default true;

    @XmlAttribute String node() default "";
}
